#include <linux/kernel.h>
#include <linux/mc146818rtc.h>
#define RTC_ALWAYS_BCD 1

#include <linux/time.h>
extern struct timeval xtime;

#include <linux/mktime.h>
extern long kernel_mktime(struct mktime *time);

void time_init(void) {
    struct mktime time;
    int i;

    /* checking for Update-In-Progress could be done more elegantly
     * (using the "update finished"-interrupt for example), but that
     * would require excessive testing. promise I'll do that when I find
     * the time.			- Torsten
     */
    /* read RTC exactly on falling edge of update flag */
    for (i = 0; i < 1000000; i++) /* may take up to 1 second... */
        if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
            break;
    for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms*/
        if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
            break;
    do { /* Isn't this overkill ? UIP above should guarantee consistency */
        time.sec = CMOS_READ(RTC_SECONDS);
        time.min = CMOS_READ(RTC_MINUTES);
        time.hour = CMOS_READ(RTC_HOURS);
        time.day = CMOS_READ(RTC_DAY_OF_MONTH);
        time.mon = CMOS_READ(RTC_MONTH);
        time.year = CMOS_READ(RTC_YEAR);
    } while (time.sec != CMOS_READ(RTC_SECONDS));
    if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
        BCD_TO_BIN(time.sec);
        BCD_TO_BIN(time.min);
        BCD_TO_BIN(time.hour);
        BCD_TO_BIN(time.day);
        BCD_TO_BIN(time.mon);
        BCD_TO_BIN(time.year);
    }
    time.mon--;
    xtime.tv_sec = kernel_mktime(&time);
    printk("year: %d\nmon:  %d\nday:  %d\n"
           "hout: %d\nmin:  %d\nsec:  %d\n",
           2000 + time.year, time.mon + 1, time.day,
           time.hour, time.min, time.sec);
}